﻿// -----------------------------------------------------------------------
// <copyright file="SPExportCmdlet.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace SPMigrationCmdlets
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Management.Automation;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Xml;
    using SharePoint.ImportExport.Core;
    using System.Data;
    using Sharepoint.ImportExport.Extractor;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    [Cmdlet(VerbsData.Export, "SPMigrationData")]
    public class Exporter : PSCmdlet
    {
        /// <summary>
        /// This is a date threshold
        /// </summary>
        private DateTime exportItemsOlderThan = DateTime.MinValue;

        /// <summary>
        /// This is a date threshold
        /// </summary>
        private DateTime exportItemsNewerThan;

        /// <summary>
        /// This is a boolean flag controlling if .aspx pages are exported
        /// </summary>
        private bool exportDesign = false;

        /// <summary>
        /// This is a boolean flag controlling if versions are exported
        /// </summary>
        private bool exportVersions;

        /// <summary>
        /// This is a boolean flag controlling if content from sub sites will be exported
        /// </summary>
        private bool includeSubWebs = false;

        /// <summary>
        /// This is the name of the directory that will contain the exported data
        /// </summary>
        private string directoryName;

        /// <summary>
        /// This is the URL to the site to be exported
        /// </summary>
        private string siteURL;

        /// <summary>
        /// This is a boolean flag controlling if user information will be exported
        /// </summary>
        private bool exportUserInfo;

        /// <summary>
        /// This is a boolean flag controlling if views will be exported
        /// </summary>
        private bool exportViews;

        /// <summary>
        /// If set only this list will be exported
        /// </summary>
        private string list;

        /// <summary>
        /// If set only this folder will be exported
        /// </summary>
        private string folder = String.Empty;

        /// <summary>
        /// Boolean flag indicating whether or not the data should be compressed
        /// </summary>
        private bool compress = false;

        /// <summary>
        /// Boolean flag indicating whether or not only content types and site columns will be exported
        /// </summary>
        private bool exportContentTypesOnly = false;
        /// <summary>
        /// Gets or sets the URL to the SharePoint site to be exported
        /// </summary>
        [Parameter(Mandatory = true)]
        public string SiteURL
        {
            get
            {
                return this.siteURL;
            }

            set
            {
                this.siteURL = value;
            }
        }


        /// <summary>
        /// Gets or sets the output directory
        /// </summary>
        [Parameter(Mandatory = true)]
        public string DirectoryName
        {
            get
            {
                return this.directoryName;
            }

            set
            {
                this.directoryName = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether subwebs should be processed
        /// </summary>
        [Parameter(Mandatory = false)]
        public SwitchParameter IncludeSubSites
        {
            get
            {
                return this.includeSubWebs;
            }

            set
            {
                this.includeSubWebs = value;
            }
        }
        /// <summary>
        /// Gets or sets the optional list parameter
        /// </summary>
        [Parameter(Mandatory = false)]
        public string List
        {
            get
            {
                return this.list;
            }

            set
            {
                this.list = value;
            }
        }

        /// <summary>
        /// Gets or sets the optional Folder that will be extracted
        /// </summary>
        [Parameter(Mandatory = false)]
        public string Folder
        {
            get
            {
                return this.folder;
            }

            set
            {
                this.folder = value;
            }
        }

        /// <summary>
        /// Gets or sets the time threshold. If set only items newer than the threshold will be exported
        /// </summary>
        [Parameter(Mandatory = false)]
        public DateTime ExportItemsNewerThan
        {
            get
            {
                return this.exportItemsNewerThan;
            }

            set
            {
                this.exportItemsNewerThan = value;
            }
        }

        /// <summary>
        /// Gets or sets the time threshold. If set only items older than the threshold will be exported
        /// </summary>
        [Parameter(Mandatory = false)]
        public DateTime ExportItemsOlderThan
        {
            get
            {
                return this.exportItemsOlderThan;
            }

            set
            {
                this.exportItemsOlderThan = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether user data will be extracted
        /// </summary>
        [Parameter(Mandatory = false)]
        public SwitchParameter ExportUserInfo
        {
            get
            {
                return this.exportUserInfo;
            }

            set
            {
                this.exportUserInfo = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether versions should be processed
        /// </summary>
        [Parameter(Mandatory = false)]
        public SwitchParameter ExportVersions
        {
            get
            {
                return this.exportVersions;
            }

            set
            {
                this.exportVersions = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether design elements should be processed
        /// </summary>
        [Parameter(Mandatory = false)]
        public SwitchParameter ExtractDesignElements
        {
            get
            {
                return this.exportDesign;
            }

            set
            {
                this.exportDesign = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether or not the data should be compressed
        /// </summary>
        [Parameter(Mandatory = false)]
        public SwitchParameter ExportViews
        {
            get
            {
                return this.exportViews;
            }
            set
            {
                this.exportViews = value;
            }
        }


        /// <summary>
        /// Gets or sets a value indicating whether or not the data should be compressed
        /// </summary>
        [Parameter(Mandatory = false)]
        public SwitchParameter ExportContentTypesOnly
        {
            get
            {
                return this.exportContentTypesOnly;
            }
            set
            {
                this.exportContentTypesOnly = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether or not the data should be compressed
        /// </summary>
        [Parameter(Mandatory = false)]
        public SwitchParameter Compress
        {
            get
            {
                return this.compress;
            }
            set
            {
                this.compress = value;
            }
        }



        protected override void ProcessRecord()
        {
            Sharepoint.ImportExport.Extractor.Exporter extractor = new Sharepoint.ImportExport.Extractor.Exporter();
            DataSet ds = new DataSet("Export Parameters");
            DataTable dt = ds.Tables.Add("Parameters");

            dt.Columns.Add("SiteURL");
            dt.Columns.Add("OutputDirectory");
            dt.Columns.Add("SiteName");
            dt.Columns.Add("List");
            dt.Columns.Add("Owner");
            dt.Columns.Add("Contact");
            dt.Columns.Add("IncludeSubWebs", typeof(bool));
            dt.Columns.Add("ManagedPath");
            dt.Columns.Add("SiteDef");
            dt.Columns.Add("Folder");
            dt.Columns.Add("ExportItemsNewerThan", typeof(System.DateTime));
            dt.Columns.Add("ExportItemsOlderThan", typeof(System.DateTime));
            dt.Columns.Add("ExportDesign", typeof(bool));
            dt.Columns.Add("ExportUsers", typeof(bool));
            dt.Columns.Add("ExportVersions", typeof(bool));
            dt.Columns.Add("ExportDoclibsOnly", typeof(bool));
            dt.Columns.Add("ProcessGalleries", typeof(bool));
            dt.Columns.Add("ExportViews", typeof(bool));
            dt.Columns.Add("DoNotExportContent", typeof(bool));

            DataRow newRow = dt.NewRow();

            // Set values in the columns:
            newRow["SiteURL"] = URL;
            newRow["OutputDirectory"] = this.DirectoryName;
            newRow["SiteName"] = String.Empty;
            newRow["List"] = List;
            newRow["Owner"] = String.Empty;
            newRow["Contact"] = String.Empty;
            newRow["IncludeSubWebs"] = this.includeSubWebs;
            newRow["ManagedPath"] = String.Empty;
            newRow["Folder"] = Folder;
            newRow["ExportItemsNewerThan"] = ExportItemsNewerThan;
            newRow["ExportDesign"] = this.exportDesign;
            newRow["ExportUsers"] = this.ignoreUserInfo;
            newRow["ExportItemsOlderThan"] = ExportItemsOlderThan;
            newRow["ExportVersions"] = this.exportVersions;
            newRow["ExportDoclibsOnly"] = false;
            newRow["ProcessGalleries"] = true;
            newRow["ExportViews"] = this.exportViews;
            newRow["DoNotExportContent"] = this.exportContentTypesOnly;

            WriteVerbose(this.ExportVersions.IsPresent.ToString());
            WriteVerbose("Exporting information from: " + this.Url + " to " + this.DirectoryName);
            WriteVerbose("Export Options:");
            WriteVerbose("Export User Information: " + this.exportUserInfo.ToString());
            if (!string.IsNullOrEmpty(List))
            {
                WriteVerbose("Export List: " + List);
            }

            WriteVerbose("Export Views: " + this.exportViews.ToString());
            WriteVerbose("Export Versions: " + this.ExportVersions.ToBool().ToString());

            if ((this.exportItemsOlderThan != DateTime.MinValue) && (this.exportItemsNewerThan != DateTime.MinValue))
            {
                WriteVerbose("Exporting items in the data range: " + this.ExportItemsNewerThan.ToString() + " - " + this.ExportItemsOlderThan.ToString());
            }
            else
            {

                if (this.exportItemsOlderThan != DateTime.MinValue)
                {
                    WriteVerbose("Export Items that are older than: " + this.ExportItemsOlderThan.ToString());
                }
                if (this.exportItemsNewerThan != DateTime.MinValue)
                {
                    WriteVerbose("Export Items that are newer than: " + this.ExportItemsNewerThan.ToString());
                }
            }
            // Add the row to the rows collection.
            dt.Rows.Add(newRow);

            if (Directory.Exists(this.DirectoryName))
            {
                Directory.SetCurrentDirectory(this.DirectoryName);
            }
            else
            {
                Directory.CreateDirectory(this.DirectoryName);
                Directory.SetCurrentDirectory(this.DirectoryName);
            }

            Logger.Init(this.DirectoryName + "\\export" + DateTime.Now.ToString("MMddHHmm") + ".log", ErrorLevel.Information);
            Logger.LogDataSendingEvent += new Logger.LogDataEventHandler(IncomingEventLogData);

            WriteVerbose("Log file: " + Logger.FileName);
           
            try
            {
                extractor.Process(ds, Compress);
            }
            catch (Exception Ex)
            {
                Console.WriteLine("Exception occurred :" + Ex.Message);
            }

            try
            {
                Logger.LogDataSendingEvent -= new Logger.LogDataEventHandler(IncomingEventLogData);
                Logger.Close();
            }
            catch (Exception Ex)
            {
            }

        }

        private void IncomingEventLogData(object sender, SPEventArgs e)
        {
            string message = e.Message;
            if (message.StartsWith("Warning-"))
            {
                message = message.Replace("Warning-", "");
                WriteWarning(message);
            }
            else if (message.StartsWith("Error-"))
            {
                message = message.Replace("Error-", "");
                ErrorRecord er = new ErrorRecord(new Exception(message.Replace("Error-", "")), "SPMIGER001", ErrorCategory.InvalidOperation, null);
                WriteError(er);
                return;
            }
            else
            {
                message = message.Replace("Information-", "");
                message = message.Replace("Progress-", "");
                string logArgs = DateTime.Now.ToLongTimeString() + "  " + message;
                WriteVerbose(logArgs);
                WriteCommandDetail(logArgs);
            }
        }
    }
}
